import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;

/**
 * @author 乐心湖
 * @version 1.0
 * @date 2021/8/31 9:29
 */

public class ChatChannel implements Runnable {
    //维护一个所有客户端的输出流，用于转发消息
    static Map<String, ObjectOutputStream> allClientOos = new HashMap<>();
    //接入的客户端socket
    private final Socket socket;
    //接入的客户端昵称
    private String name;
    //当前进来的客户端的输入流
    private ObjectInputStream ois;
    //当前进来的客户端的输出流
    private ObjectOutputStream oos;
    //首次连接服务端
    private boolean first = true;
    //当前客户端连接是否被关闭
    private boolean currentClientCloesed = false;

    public ChatChannel(Socket socket) {
        this.socket = socket;
    }

    @Override
    public void run() {
        while (true) {
            try {
                //首次连接服务端
                if (first) {
                    ois = new ObjectInputStream(socket.getInputStream());
                    oos = new ObjectOutputStream(socket.getOutputStream());
                    //用户名
                    name = (String) ois.readObject();
                    //收集
                    allClientOos.put(name, oos);
                    System.out.println(name + "，进入聊天室！");
                    //群发消息，通知每个用户
                    for (ObjectOutputStream oos : allClientOos.values()) {
                        oos.writeObject("系统消息：" + name + "，进入聊天室");
                        oos.flush();
                    }
                    first = false;
                    currentClientCloesed = false;
                }
                if (!currentClientCloesed) {
                    //获取消息
                    String msg = (String) ois.readObject();
                    System.out.println("@" + name + "：" + msg);
                    //判断私聊，私聊具体对象
                    if (msg.startsWith("@") && msg.contains("#")) {
                        //私聊规则：@昵称#内容
                        String toName = msg.substring(1, msg.indexOf("#"));
                        msg = msg.substring(msg.indexOf("#") + 1);
                        if (allClientOos.containsKey(toName)) {
                            allClientOos.get(toName).writeObject("@" + name + "悄悄跟你说：" + msg);
                        } else {
                            oos.writeObject("系统消息：该用户未在线");
                        }
                    } else {
                        for (ObjectOutputStream oos : allClientOos.values()) {
                            oos.writeObject("@" + name + "：" + msg);
                        }
                    }
                    oos.flush();
                }
            } catch (Exception e) {
                try {
                    if (name != null) {
                        System.out.println(name + "，离开聊天室！");
                        //关闭当前客户端
                        socket.close();
                        currentClientCloesed = true;
                        allClientOos.remove(name);
                        for (ObjectOutputStream oos : allClientOos.values()) {
                            oos.writeObject("系统消息：" + name + "离开聊天室");
                        }
                    }
                } catch (IOException ioException) {
                    ioException.printStackTrace();
                }
            }
        }
    }
}
